Lambdaの関数とレイヤーのストレージがデフォルト上限(75GB)に達してしまった時に対応したこと
はじめに
オペレーション部サービスグロースチームの筧です。
先日、チーム用のAWSアカウントで以下のエラーが発生しました。 当該エラーの概要と実施した対処方法をご紹介します。
You've exceeded your account's function and layer storage limit for this Region (75.0 GB).
エラー概要
Serverless FrameworkでLambdaをデプロイしようとした時に当該エラーが発生しました。 AWS公式ドキュメントには当該エラーについて以下の記載がありました。
リソース
アップロードされた関数 (.zip ファイルアーカイブ) とレイヤーのストレージ。各関数バージョンとレイヤーバージョンは、ストレージを消費します。デフォルトのクォータ
75 GB引き上げることができる最大
Terabytes
上記から、Lambdaの関数とレイヤーのストレージが、デフォルトのクォータの75GBに達してしまったのだろうと判断しました。 Serverless FrameworkはAWSから以前のバージョンの関数を削除しないため、改修を繰り返すたびに以前のバージョンの関数が積み上がってしまっていたようです。
実施した対処方法
はじめに、暫定対応としてService Quotasによる上限緩和を検討しました。 前述のAWS公式ドキュメントに、「引き上げることができる最大」が「Terabytes」と記載があったとおり、Service Quotasによる上限緩和が可能です。 申請した結果、数時間で150GBに緩和いただけました。
次いで、恒久対応としてServerless Frameworkのプラグインである、serverless-prune-pluginの利用を検討しました。 serverless-prune-pluginは下記の通り、指定したバージョン(3世代前とか)の関数などは残して後は消してくれるプラグインです。
Following deployment, the Serverless Framework does not purge previous versions of functions from AWS, so the number of deployed versions can grow out of hand rather quickly. This plugin allows pruning of all but the most recent version(s) of managed functions from AWS. This plugin is compatible with Serverless 1.x and higher.
やってみた
serverless-prune-pluginの導入方法をご紹介します。
既存のディレクトリでサービスを開始します。
$ cd {サービスのディレクトリ} $ serverless create --template aws-python3 Serverless: Generating boilerplate... Serverless: Successfully generated boilerplate for template: "aws-python3" Serverless: NOTE: Please update the "service" property in serverless.yml with your service name
ディレクトリ階層は以下です。
$ tree . ├── LICENSE ├── README.md ├── handler.py └── serverless.yml
Serverlessプラグインコマンドでserverless-prune-pluginをインストールします。
$ sls plugin install -n serverless-prune-plugin Serverless: Installing plugin "serverless-prune-plugin@latest" (this might take a few seconds...) Serverless: Successfully installed "serverless-prune-plugin@latest"
ディレクトリ階層は以下のようになります。
$ tree -L 1 . ├── LICENSE ├── README.md ├── handler.py ├── node_modules ├── package-lock.json ├── package.json └── serverless.yml
serverless.ymlを確認すると、pluginsにserverless-prune-pluginが自動で追加されています。
3世代だけ残して後は自動で削除するために、serverless.ymlを編集します。 下記ハイライトの箇所を追加することで、当該設定ができました。(主旨とは直接関係ないmemorySizeなどを追加しています)
service: serverless-prune-plugin frameworkVersion: "2" provider: name: aws runtime: python3.8 lambdaHashingVersion: 20201221 stage: ${opt:stage, 'dev'} region: ${opt:region, 'ap-northeast-1'} memorySize: 256 custom: prune: automatic: true number: 3 functions: hello: handler: handler.hello package: patterns: - "!.git/**" - "!node_modules/**" - "!package-lock.json" plugins: - serverless-prune-plugin
serverless-prune-pluginが機能するか確認してみます。 初回はデプロイが完了した後に、初回バージョンが追加された旨が表示されています。
$ sls deploy --stage dev {省略} Serverless: Prune: Running post-deployment pruning Serverless: Prune: Querying for deployed function versions Serverless: Prune: serverless-prune-plugin-dev-hello has 1 additional version published and 0 aliases, 0 versions selected for deletion
serverless-prune-pluginが機能するか確認してみます。 handlers.pyの内容を修正して、sls deployを複数回繰り返します。 下記ハイライトの箇所の通り、4回目のデプロイが完了した後に、初回バージョン(3世代より前)は自動で削除されていることが確認できました。
$ sls deploy --stage dev {省略} Serverless: Prune: Running post-deployment pruning Serverless: Prune: Querying for deployed function versions Serverless: Prune: serverless-prune-plugin-dev-hello has 4 additional versions published and 0 aliases, 1 version selected for deletion Serverless: Prune: Deleting Function serverless-prune-plugin-dev-hello v1... Serverless: Prune: Pruning complete.
おわりに
serverless-prune-pluginを利用することで簡単にLambdaの関数とレイヤーのストレージを減らすことができました。 Serverless Frameworkご利用の方は、サービス開始時に当該プラグインを入れてみてはいかがでしょうか。